#include "..\include\atomic.h"
#include <windows.h>

namespace{
	
	template< class A, class B > struct max_size{ static const size_t POINT_SIZE = sizeof(A) > sizeof(B) ? sizeof(A) : sizeof(B); };

	template <typename T>
	inline T* get_aligned_ptr(){
		return static_cast<T*>(
			_aligned_malloc(sizeof(T), max_size<long,T>::POINT_SIZE ) );
	}
	template <typename T>
	inline void free_aligned_ptr(T*& ptr)
	{
		_aligned_free((void*)ptr);
		ptr = nullptr;
	}
}

namespace sys{

	class atomic_impl_win32: public atomic
	{
	public:
		typedef atomic::T	T;
		typedef long		VT;

		atomic_impl_win32(T val)
		{
			m_val = get_aligned_ptr<VT>();
			InterlockedExchange(m_val, val);
		}

		virtual ~atomic_impl_win32()
		{
			free_aligned_ptr(m_val);
		}

		virtual T count()
		{
			return *m_val;
		}

		virtual T increase()
		{
			return InterlockedIncrement(m_val);
		}

		virtual T decrease()
		{
			return InterlockedDecrement(m_val);
		}

		virtual T exchange(T _ex)
		{
			return InterlockedExchange(m_val, _ex);
		}

		virtual bool compare_exchange(T _cmp, T _ex)
		{
			return	(InterlockedCompareExchange(m_val, _ex, _cmp) != _ex);
		}

		virtual T fetch_add(T _val)
		{
			return InterlockedExchangeAdd(m_val, _val) + _val;
		}

		virtual T fetch_sub(T _val)
		{
			return InterlockedExchangeAdd(m_val, -_val) - _val;
		}

		virtual T fetch_and(T _val)
		{
			return InterlockedOr(m_val, _val) & _val;
		}

		virtual T fetch_or(T _val)
		{
			return InterlockedOr(m_val, _val) | _val;
		}

		virtual T fetch_xor(T _val)
		{
			return InterlockedXor(m_val, _val) ^ _val;
		}

	private:
		volatile long* m_val;
	};
}